SideButton Dashboard Knowledge Module
SideButton Dashboard Settings — Knowledge Module Reference
SideButton Dashboard knowledge module — UI selectors, data model, and page states documenting Settings.
sidebutton install SideButton Dashboard - Path
- /settings
- Verified
- 2026-02-21
- Confidence
- 96%
- Role playbooks
- 0
- Pack
- SideButton Dashboard
- Domain
- sidebutton.local
What This Is
The Settings page is the configuration hub for SideButton's AI context system and LLM provider. It has two top-level tabs: AI Context (managing persona, roles, targets, integrations, and inline contexts that get injected into every LLM call) and LLM Provider (configuring which AI model to use). The AI Context tab has five sub-tabs, making this the most complex page in the dashboard.
URL Patterns
| View | URL | Notes |
|---|---|---|
| Settings | /settings | Single URL — all tab/sub-tab state is component-local, not reflected in URL |
No URL-based routing for individual tabs. Tab state resets on navigation away and back.
Page Structure
+--[Header: Back button + "Settings" heading]-------------+
| [.error-banner] shown when error (red, below header) |
| [.success-banner] shown on save success (green) |
| |
| [Top Tabs: AI Context | LLM Provider] |
| |
| === AI Context tab selected === |
| [Sub-tabs: Persona | Roles (N) | Targets (N) | |
| Integrations (N) | Inline (N)] |
| |
| [Tab content area — varies by sub-tab] |
| - Persona: textarea + Save button |
| - Roles: list with toggle/edit/delete per item |
| - Targets: list with toggle/edit/delete per item |
| - Integrations: provider cards with connector options |
| - Inline: LLM Contexts section + Env Variables section|
| |
| === LLM Provider tab selected === |
| [.llm-form-row: two-column grid] |
| Left col: Provider select, Base URL, API Key, Model |
| + Test Connection + Save buttons |
| Right col: Status panel (Configured/Provider/Model) |
| + test result message |
+----------------------------------------------------------+
Key Elements
Header
| Element | Selector | Notes |
|---|---|---|
| Back button | .back-btn | SVG arrow + "Back" text. Calls navigateBack() |
| Settings heading | h1 containing "Settings" | Page title |
Banners (below header, above content)
| Element | Selector | Notes |
|---|---|---|
| Error banner | .error-banner | Red background (#fef2f2), red text (#b91c1c). Shown when API call fails |
| Success banner | .success-banner | Green background (#f0fdf4), green text (#15803d). Auto-hides after 3s via setTimeout |
Top-Level Tabs
| Element | Selector | Notes |
|---|---|---|
| AI Context tab | button "AI Context" | Default active. Shows context sub-tabs |
| LLM Provider tab | button "LLM Provider" | Shows LLM configuration form |
AI Context Sub-Tabs
| Element | Selector | Notes |
|---|---|---|
| Persona tab | button "Persona" | Textarea editor for persona markdown |
| Roles tab | button "Roles" | Shows count badge (e.g., "73"). All roles including system roles |
| Targets tab | button "Targets" | Shows count badge for user-editable targets only (provider-managed targets excluded) |
| Integrations tab | button "Integrations" | Count badge = number of connected providers |
| Inline tab | button "Inline" | Count badge = total user_contexts count (LLM + env vars combined) |
Persona Sub-Tab
| Element | Selector | Notes |
|---|---|---|
| Persona textarea | textbox "Describe who you are..." | Monospace, min-height 300px. Pre-filled with persona.md content |
| Character count | right-aligned text near textarea | Shows "{N} chars" |
| Save Persona button | button "Save Persona" | Disabled when no changes (dirty tracking inside PersonaEditor component) |
Roles Sub-Tab
| Element | Selector | Notes |
|---|---|---|
| Add Role button | .btn-add containing "+ Add Role" | Opens RoleTargetModal in role mode |
| Role item (normal) | .context-item (without .deleting) | Per-role card row |
| Role item (inactive) | .context-item.inactive | opacity: 0.5 when role.enabled === false |
| Role item (deleting) | .context-item.deleting | Replaces card with inline confirm UI; red bg (#fef2f2) |
| Role name | .item-name span | Bold, font-size 0.9rem |
| System badge | .tag.system | Gray badge with text "system". Shown when filename.startsWith('_') |
| Match pattern tags | .tag.match | One per match pattern (e.g., "@engineering"). Gray-blue background |
| Item actions | .item-actions | Contains Edit + × buttons. opacity: 0 by default, opacity: 1 on .context-item:hover |
| Edit button | .btn-edit | Text "Edit". Opens RoleTargetModal pre-filled |
| Delete (×) button | .btn-delete | Shows "×" character. Not rendered for system roles (filename starts with _) |
| Toggle switch | button.toggle-switch | Custom button component, NOT a native checkbox/toggle |
| Toggle on state | button.toggle-switch.on | Green background (#22c55e). title="Enabled" |
| Toggle off state | button.toggle-switch (no .on) | Gray background (#d1d5db). title="Disabled" |
| Toggle knob | .toggle-knob span inside toggle | White circle that slides; transform: translateX(16px) when on |
Inline Delete Confirm UI (Roles/Targets)
When .btn-delete (×) is clicked, deletingFilename is set and the card transforms to:
| Element | Selector | Notes |
|---|---|---|
| Confirm container | .context-item.deleting | Red-tinted card replacing normal item |
| Confirm message | p inside .context-item.deleting | Text: Delete "{name}"? in red (#b91c1c) |
| Cancel button | .btn-cancel-sm | White button, text "Cancel". Clears deletingFilename |
| Confirm delete button | .btn-delete-confirm | Red (#ef4444) button, text "Delete". Executes API delete |
Targets Sub-Tab
| Element | Selector | Notes |
|---|---|---|
| Add Target button | .btn-add containing "+ Add Target" | Opens RoleTargetModal in target mode |
| Target items | Same .context-item structure as roles | Identical layout and delete/toggle pattern |
| Provider-managed targets | Not shown here | Targets with a provider field are filtered out of this tab |
The delete inline confirm pattern is identical to Roles: .context-item.deleting with .btn-cancel-sm + .btn-delete-confirm.
Integrations Sub-Tab
| Element | Selector | Notes |
|---|---|---|
| Provider card | .provider-card | One per provider; gray background, rounded border |
| Provider name | .item-name inside .provider-info | Bold text (e.g., "Jira", "Slack") |
| Provider type badge | .tag.match inside .provider-info | Text format: "{type} provider". Multi-type providers (e.g., GitHub) render multiple .tag.match badges — one per type string in the array |
| Status: connected | .tag.provider-connected | Green (#dcfce7 bg, #15803d text). Text: "Connected" |
| Status: connector set but not ready | .tag.provider-missing | Yellow (#fef3c7 bg, #92400e text). Text: "Not available" |
| Status: no connector | .tag.provider-not-configured | Gray (#f3f4f6 bg, #6b7280 text). Text: "Not connected" |
| Connector row | .connector-row | One per connector option |
| Active connector row | .connector-row.active | Blue-tinted border (#93c5fd) + background (#eff6ff) |
| Connector radio input | input[type="radio"] | Wrapped in .connector-radio label. onchange → handleConnectorChange() — auto-saves immediately |
| Connector name | .connector-name span | e.g., "REST API", "CLI (acli)", "Browser" |
| Active badge | .tag.connector-active | Blue (#dbeafe bg, #1d4ed8 text). Text: "active" |
| Feature level | .connector-level span | Text: "{level} features" (e.g., "Full features", "Basic features") |
| Ready status | .req-met span | Green text. Text: "Ready" |
| Error/missing status | .req-missing span | Orange-brown text, monospace. Text: error message (e.g., "Missing: JIRA_URL") |
| Setup toggle button | .btn-setup-toggle | Text toggles between "Setup" and "Hide setup" |
| Setup instructions panel | .setup-instructions | Shown when expandedSetup === setupKey. Contains <p> with conn.setupInstructions text |
| Env var requirements | .env-requirements div inside .setup-instructions | Flex row of code.env-var-check elements |
| Env var code badge | code.env-var-check | Monospace, cyan (#e0f2fe bg, #0369a1 text). One per required env var |
Inline Sub-Tab
The inline tab has two sub-sections rendered inside .context-sections:
| Element | Selector | Notes |
|---|---|---|
| Add button | .btn-add containing "+ Add" | Opens ContextModal |
| Sections wrapper | .context-sections | Flex column with 24px gap |
| LLM Contexts section | .context-section (first) | <h3>LLM Contexts</h3> heading |
| Env Variables section | .context-section (second) | <h3>Environment Variables</h3> heading |
| Env Variables empty state | .context-section (second) when empty | Text: "No environment variables configured" + "Add variables accessible via {{env.name}}" |
LLM Context Items
| Element | Selector | Notes |
|---|---|---|
| Context item | .context-item | Normal card when not deleting |
| Context item deleting | .context-item.deleting | Inline confirm: "Delete this context?" + Cancel + Delete |
| Industry tag | .tag.industry | Blue (#dbeafe bg, #1d4ed8 text). Shown when ctx.industry set |
| Domain tag | .tag.domain | Purple (#f3e8ff bg, #7c3aed text). Shown when ctx.domain set |
| Global tag | .tag.global | Gray (#e5e7eb bg, #6b7280 text). Shown when neither industry nor domain set |
| Context text | .context-text p | 2-line clamp preview of context body |
| Item actions | .item-actions | opacity: 0 default → opacity: 1 on .context-item:hover |
| Edit button | .btn-edit | Text "Edit". Opens ContextModal pre-filled |
| Delete button | .btn-delete | Shows "×". Calls confirmDelete(ctx.id) → sets deletingId |
Environment Variable Items
| Element | Selector | Notes |
|---|---|---|
| Env item container | .context-item.env-item | Horizontal flex row (align-items: center, gap: 12px) |
| Env item deleting | .context-item.env-item.deleting | Column layout with "Delete this variable?" + Cancel + Delete |
| Variable name | code.env-name | Monospace, cyan (#e0f2fe bg, #0369a1 text). e.g., "github_base_path" |
| Variable value | .env-value span | Monospace, truncated with ellipsis. e.g., "/Users/me/Documents/GitHub" |
| Item actions | .item-actions | opacity: 0 default → opacity: 1 on .env-item:hover |
Inline Delete Confirm UI (Inline Tab)
Same visual pattern as Roles/Targets but uses deletingId state (separate from deletingFilename):
| Element | Selector | Notes |
|---|---|---|
| LLM context confirm text | p in .context-item.deleting | Text: "Delete this context?" |
| Env var confirm text | p in .context-item.env-item.deleting | Text: "Delete this variable?" |
| Cancel | .btn-cancel-sm | Clears deletingId |
| Delete | .btn-delete-confirm | Executes delete then calls handleSave() to persist |
LLM Provider Tab
| Element | Selector | Notes |
|---|---|---|
| Layout wrapper | .llm-form-row | CSS grid, grid-template-columns: 1fr 1fr. Collapses to single column below 700px |
| Provider select | select#provider | Native <select>. Options: OpenAI, Anthropic, Ollama. onchange calls handleProviderChange() |
| Base URL input | input#base-url | Text input. Auto-filled by handleProviderChange() |
| API Key label | label[for="api-key"] | Contains "API Key" text + .toggle-visibility button |
| Show/Hide toggle | .toggle-visibility button | Inside the label. Text: "Show" or "Hide". Toggles type="password" ↔ type="text" |
| API Key input | input#api-key | Password field by default. Placeholder: "sk-..." |
| API Key action button | ... button inside API Key input | Small "..." button on right side of field. Purpose: additional input action |
| Base URL action button | ... button inside Base URL input | Small "..." button on right side of field. Same pattern as API Key |
| Model input | input#model | Text input. Auto-filled by handleProviderChange(). Placeholder: "gpt-4o" |
| Test Connection button | .btn-secondary | Text "Test Connection" / "Testing..." when active. Disabled during test |
| Save button | .btn-primary | Text "Save" / "Saving..." when active. Disabled during save |
| Status panel | .status-section | Right column. Shows LLM Configured, Provider, Model values |
| LLM Configured value | .status-value.yes (green) / .status-value.no (orange) | "Yes" when apiKey truthy, "No" when empty |
| Test result | .test-result.success or .test-result.error | Appears after Test Connection. Auto-hides after 4s |
Modals
| Modal | Trigger | Fields |
|---|---|---|
| RoleTargetModal (role mode) | "+ Add Role" or Edit on a role | Name (required), Match patterns (comma-separated @tags), Body (markdown textarea) |
| RoleTargetModal (target mode) | "+ Add Target" or Edit on a target | Name (required), Match patterns (comma-separated domains/globs), Body (markdown textarea) |
| ContextModal (LLM context) | "+ Add" in Inline tab, Edit on LLM context | Type selector, Industry dropdown, Domain input, Context textarea |
| ContextModal (env variable) | "+ Add" in Inline tab, Edit on env var | Type selector, Variable name, Variable value |
Data Model
Persona
| Field | Type | Notes |
|---|---|---|
| body | string | Markdown content of persona file |
Role
| Field | Type | Notes |
|---|---|---|
| filename | string | File identifier (e.g., "ai-tools.md", "_system.md") |
| name | string | Display name (e.g., "AI Tools") |
| match | string[] | Pattern tags (e.g., ["@engineering"]) |
| body | string | Markdown instructions |
| enabled | boolean | Whether role is active. Treated as true when undefined (only === false is disabled) |
Target
| Field | Type | Notes |
|---|---|---|
| filename | string | File identifier |
| name | string | Display name (e.g., "GitHub") |
| match | string[] | Domain patterns (e.g., ["github.com", "github_*"]) |
| body | string | Markdown instructions |
| enabled | boolean | Whether target is active |
| provider | string | Optional. If set, target is provider-managed (filtered from Targets tab, shown in Integrations) |
LLM Config (stored as settings.llm)
| Field | Type | Notes |
|---|---|---|
| provider | string | "openai", "anthropic", or "ollama" |
| base_url | string | API endpoint URL |
| api_key | string | API key (masked as password in UI by default) |
| model | string | Model identifier string |
LLM Provider Defaults (auto-filled on provider change)
| Provider ID | Display Name | Default Base URL | Default Model |
|---|---|---|---|
| openai | OpenAI | https://api.openai.com/v1 | gpt-4o |
| anthropic | Anthropic | https://api.anthropic.com | claude-3-5-sonnet-latest |
| ollama | Ollama | http://localhost:11434/v1 | llama3.2 |
Provider Status
| Field | Type | Notes |
|---|---|---|
| id | string | Provider identifier |
| name | string | Display name |
| type | string or string[] | Provider type(s); rendered as "{type} provider" |
| connected | boolean | True if active connector is ready |
| activeConnector | string or null | Currently selected connector ID |
| connectors | array | Available connector definitions (id, name, featureLevel, setupInstructions, requiredEnvVars) |
| connectorStatuses | array | Status per connector (active, available, error) |
Known Providers (observed live, 2026-03-25)
| Provider | Type(s) | Connectors |
|---|---|---|
| Jira | issues provider | REST API, CLI (acli), Browser |
| Slack | chat provider | Bot Token API, Browser |
| GitHub | git, issues provider | CLI (gh), Browser |
| Bitbucket | git provider | REST API 2.0 |
Note: GitHub shows two type badges ("git" and "issues provider") because its type is an array. Bitbucket is a single-type provider.
User Context (Inline tab)
| Field | Type | Notes |
|---|---|---|
| id | string | Unique identifier |
| type | "llm" or "env" | Determines which sub-section it renders in |
| industry | string | (LLM type) Optional. Drives .tag.industry display |
| domain | string | (LLM type) Optional. Drives .tag.domain display |
| context | string | (LLM type) The LLM instruction text |
| name | string | (env type) Variable name |
| value | string | (env type) Variable value |
States
| State | Trigger | Visual Indicator |
|---|---|---|
| Default (AI Context > Persona) | Page load | Persona textarea with content, Save Persona disabled |
| Persona dirty | Edit textarea | Save Persona button enabled |
| Role/target inactive | enabled === false | .context-item.inactive — opacity: 0.5 (0.7 on hover) |
| Inline delete pending | Click × on role/target | .context-item.deleting replaces card with red confirm UI |
| Inline delete pending (inline tab) | Click × on context/env var | Same .context-item.deleting pattern, uses deletingId |
| Item actions visible | Hover over .context-item | .item-actions opacity transitions from 0 → 1 |
| LLM Provider tab | Click LLM Provider tab | Two-column grid form + status panel |
| Connector active | Radio selected for connector | .connector-row.active — blue-tinted |
| Setup expanded | Click "Setup" button | .setup-instructions panel visible below connector row |
| Saving | Click Save | .btn-primary shows "Saving...", disabled |
| Testing | Click Test Connection | .btn-secondary shows "Testing...", disabled |
| Test result | After test completes | .test-result.success or .test-result.error — auto-hides after 4s |
| Save success | API save succeeds | .success-banner appears above content — auto-hides after 3s |
| Error | Any API failure | .error-banner appears above content |
| Loading | Initial page load | .loading div with "Loading settings..." text |
Common Tasks
- Edit persona: Navigate to Settings → Persona sub-tab (default) → edit textarea → click "Save Persona"
- Add role: Roles sub-tab → click "+ Add Role" → fill Name, Match patterns, Body in modal → submit
- Toggle role on/off: Roles sub-tab → hover role item → click
button.toggle-switch— auto-saves via API - Edit role: Roles sub-tab → hover role item → click Edit (
.btn-edit) → modify in modal → submit - Delete role: Roles sub-tab → hover role item → click × (
.btn-delete) → click "Delete" in inline confirm — system roles (filename starts with_) have no × button - Add target: Targets sub-tab → click "+ Add Target" → fill form → submit
- Toggle target: Same as role toggle pattern
- Change integration connector: Integrations sub-tab → click radio input (
input[type="radio"]) on desired connector → auto-saves immediately (no separate save button) - View setup instructions: Integrations sub-tab → click "Setup" on connector row → reads
.setup-instructionspanel - Add inline LLM context: Inline sub-tab → click "+ Add" → ContextModal opens → choose type/industry/domain/context → submit
- Add env variable: Inline sub-tab → click "+ Add" → ContextModal opens → select env type → fill name + value → submit
- Delete inline context/env var: Inline sub-tab → hover item → click × → inline confirm appears → click "Delete"
- Configure LLM provider: LLM Provider tab → select provider from
select#provider(auto-fills URL + model) → enter API key → click "Save" - Test LLM connection: LLM Provider tab → fill config → click "Test Connection" → result appears for 4s
Tips
- Tab badges show counts: Roles = all roles count; Targets = user-editable targets only; Integrations = connected provider count; Inline = total user_contexts
- Hover to see actions: Edit and × buttons are invisible (opacity: 0) until hovering the card — snapshot alone will not capture them
- Persona is global: Injected into every LLM call regardless of context
- Roles vs Targets: Roles define behavior for @category tags (situations/topics). Targets define behavior for domain URL patterns (specific sites)
- System roles are protected: Roles with filenames starting with
_show a.tag.system"system" badge and have no × delete button rendered - Provider-managed targets hidden from Targets tab: Targets with a
providerfield are filtered out — managed by integrations - LLM Provider auto-fills on provider change: Selecting a different provider in the dropdown immediately sets Base URL and Model to defaults
- Connector radio is a toggle: Clicking an already-active connector's radio calls
handleConnectorChange(prov.id, null)— deactivating it - Scroll position preserved: Toggle and edit operations on roles/targets use
preserveScroll()to maintain scroll position - Test Connection is format-only: Does NOT make a real API call. Only checks apiKey non-empty and OpenAI keys start with "sk-"
Gotchas
- No URL-based tab state: All tab/sub-tab selection is component-local. Navigating away and back always resets to AI Context > Persona
- Delete uses INLINE confirm, not native confirm(): Clicking × does NOT open a browser confirm() dialog. It sets
deletingFilename(roles/targets) ordeletingId(inline tab), transforming the card into.context-item.deletingwith.btn-cancel-smand.btn-delete-confirmbuttons in-place - Item actions hidden by default:
.item-actionshasopacity: 0at rest. Must hover.context-itemto reveal Edit and × buttons — accessibility snapshot may not show them - Toggle switch is a custom button:
button.toggle-switch, NOT a native<input type="checkbox">or<input type="toggle">. Use.click()orref-based click, notselect_option() - Provider select is native:
select#providerIS a native<select>element — useselect_option()or keyboard interaction, not click-based dropdown - Success banner auto-hides in 3s: Must screenshot immediately after save action to capture it
- Test result auto-hides in 4s: Same — screenshot immediately after Test Connection
- inactive items at half opacity:
.context-item.inactive(disabled roles/targets) renders at opacity: 0.5 — may be harder to see in screenshots - Inline tab count includes both LLM and env contexts: The badge on the Inline sub-tab is
userContexts.length(combined), not separate counts - Integrations badge is connected count: Shows only providers where
connected === true, not total provider count - SPA 404 on direct navigation:
/settingsreturns 404 JSON if loaded directly — must navigate through SPA root first - Connector radio deselects when re-clicked: Clicking an active connector's radio sends
nullas connectorId, disconnecting it